package cn.iocoder.yudao.module.system.framework.aop;

import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.config.UserActivityProperties;
import cn.iocoder.yudao.module.system.service.useractivity.UserActivityRecordService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * 用户活动记录AOP切面
 * 
 * @author 系统开发团队
 */
@Aspect
@Component
@Slf4j
public class UserActivityAspect {

    @Resource
    private UserActivityRecordService userActivityRecordService;

    @Resource
    private UserActivityProperties userActivityProperties;

    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    /**
     * 定义Controller切点
     */
    @Pointcut("@within(org.springframework.web.bind.annotation.RestController) || " +
              "@within(org.springframework.stereotype.Controller)")
    public void controllerPointcut() {}

    /**
     * 定义业务方法切点
     */
    @Pointcut("execution(* cn.iocoder.yudao.module.*.service.*.*(..)) && " +
              "!execution(* cn.iocoder.yudao.module.system.service.useractivity.*.*(..))")
    public void businessMethodPointcut() {}

    /**
     * 记录功能使用活动
     */
    @AfterReturning("controllerPointcut()")
    public void recordFeatureUsage(JoinPoint joinPoint) {
        if (!userActivityProperties.getEnable() || !isRecordTypeEnabled("feature_use")) {
            return;
        }

        try {
            HttpServletRequest request = ServletUtils.getRequest();
            if (request == null || shouldSkipRecording(request)) {
                return;
            }

            LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
            if (loginUser == null) {
                return;
            }

            String featureName = buildFeatureName(joinPoint, request);
            String clientIp = ServletUtils.getClientIP(request);
            String userAgent = request.getHeader("User-Agent");

            userActivityRecordService.recordFeatureUseActivity(
                loginUser.getId(),
                getUsernameFromLoginUser(loginUser),
                loginUser.getUserType(),
                featureName,
                clientIp,
                userAgent,
                null
            );

        } catch (Exception e) {
            log.error("[UserActivityAspect] 记录功能使用活动失败", e);
        }
    }

    /**
     * 记录业务操作活动
     */
    @AfterReturning("businessMethodPointcut()")
    public void recordBusinessOperation(JoinPoint joinPoint) {
        if (!userActivityProperties.getEnable() || !isRecordTypeEnabled("feature_use")) {
            return;
        }

        try {
            HttpServletRequest request = ServletUtils.getRequest();
            if (request == null) {
                return;
            }

            LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
            if (loginUser == null) {
                return;
            }

            String featureName = buildBusinessFeatureName(joinPoint);
            String clientIp = ServletUtils.getClientIP(request);
            String userAgent = request.getHeader("User-Agent");

            userActivityRecordService.recordFeatureUseActivity(
                loginUser.getId(),
                getUsernameFromLoginUser(loginUser),
                loginUser.getUserType(),
                featureName,
                clientIp,
                userAgent,
                null
            );

        } catch (Exception e) {
            log.error("[UserActivityAspect] 记录业务操作活动失败", e);
        }
    }

    /**
     * 判断是否应该跳过记录
     */
    private boolean shouldSkipRecording(HttpServletRequest request) {
        String requestUri = request.getRequestURI();

        // 检查是否为静态资源
        if (isStaticResource(requestUri)) {
            return true;
        }

        // 检查是否在排除路径中
        for (String excludePath : userActivityProperties.getExcludePaths()) {
            if (pathMatcher.match(excludePath, requestUri)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 构建功能名称
     */
    private String buildFeatureName(JoinPoint joinPoint, HttpServletRequest request) {
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        String moduleName = extractModuleName(request.getRequestURI());
        
        return String.format("%s.%s.%s", moduleName, className, methodName);
    }

    /**
     * 构建业务功能名称
     */
    private String buildBusinessFeatureName(JoinPoint joinPoint) {
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        String packageName = joinPoint.getTarget().getClass().getPackage().getName();
        
        // 从包名中提取模块名
        String moduleName = "unknown";
        if (packageName.contains(".module.")) {
            String[] parts = packageName.split("\\.module\\.");
            if (parts.length > 1) {
                String[] moduleParts = parts[1].split("\\.");
                if (moduleParts.length > 0) {
                    moduleName = moduleParts[0];
                }
            }
        }
        
        return String.format("business.%s.%s.%s", moduleName, className, methodName);
    }

    /**
     * 从URI中提取模块名称
     */
    private String extractModuleName(String requestUri) {
        if (StrUtil.isBlank(requestUri)) {
            return "unknown";
        }

        // 匹配 /admin-api/{module}/ 格式
        if (requestUri.startsWith("/admin-api/")) {
            String[] parts = requestUri.split("/");
            if (parts.length > 2) {
                return parts[2];
            }
        }

        return "unknown";
    }

    /**
     * 判断是否为静态资源
     */
    private boolean isStaticResource(String requestUri) {
        if (StrUtil.isBlank(requestUri)) {
            return false;
        }

        // 检查文件扩展名
        for (String extension : userActivityProperties.getExcludeExtensions()) {
            if (requestUri.toLowerCase().endsWith(extension)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断是否启用指定的记录类型
     */
    private boolean isRecordTypeEnabled(String recordType) {
        return userActivityProperties.getRecordTypes().contains(recordType);
    }

    /**
     * 从LoginUser中获取用户名
     */
    private String getUsernameFromLoginUser(LoginUser loginUser) {
        if (loginUser.getInfo() != null && loginUser.getInfo().containsKey(LoginUser.INFO_KEY_NICKNAME)) {
            return loginUser.getInfo().get(LoginUser.INFO_KEY_NICKNAME);
        }
        return String.valueOf(loginUser.getId());
    }
}